<?php


namespace App\Http\Services;

use App\Models\Menu;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class MenuService extends BaseService
{

    public function all(){
        $result = Menu::orderBy('sort','asc')->orderBy('id','desc')->get();
        return $result->transform(function($item){
            return [
                'id'=>$item->id,
                'name'=>$item->name,
                'value'=>$item->value
            ];
        });
    }

    public function tree(){
        $menus = Menu::orderBy('sort','asc')->get()->toArray();
        foreach ($menus as $k=>&$v){
            $v['routeName'] = $v['route_name'];
            $v['routePath'] = $v['route_path'];
            $v['path'] = $v['route_path'];
            $v['parentId'] = $v['parent_id'];
        }
        $menu = $this->buildTree($menus);
        return $menu;
    }

    public function getRoutes(){
        $user = $this->getCurrentUser();
        $menu = Cache::get('user_menus_key_'.$user->id);
        if(empty($menu)){
            Log::info('menu 无数据');
            $menus = $user->roles()->with(['menus'=>function($q){
                $q->where('visible',1)->whereNotIn('type',['BUTTON'])->orderBy('sort','asc');
            }])->get()->pluck('menus')->flatten()->unique()->toarray();
            // 测试全部返回
            //$menus = Menu::where('visible',1)->whereNotIn('type',['BUTTON'])->orderBy('sort','asc')->get()->toArray();

            $newMenus = [];
            foreach ($menus as $k=>$v){
                $newMenus[$k]['id'] = $v['id'];
                $newMenus[$k]['path'] = $v['route_path'];
                $newMenus[$k]['component'] = $v['component'];
                $newMenus[$k]['redirect'] = $v['redirect'];
                $newMenus[$k]['name'] = $v['route_name'] ?: $v['route_path'];
                $newMenus[$k]['parent_id'] = $v['parent_id'];
                $newMenus[$k]['meta'] = [
                    'title'=>$v['name'],
                    'icon'=>$v['icon'],
                    'hidden'=>false,
                    'alwaysShow'=>$v['always_show'] ? true : false,
                    'params'=> $v['params'] && $v['params'] != '[]' ? json_decode($v['params'],true) : null
                ];
                if($v['keep_alive']){
                    $newMenus[$k]['meta']['keepAlive'] = true;
                }
            }
            $menu = $this->buildTree($newMenus);
            Cache::put('user_menus_key_'.$user->id,$menu,now()->addMinutes(15));
        }else{
            Log::info('menu 有数据');
        }

        //dd($menu);
        return $menu;
    }


    public function optionTree(){
        $menus = Menu::orderBy('sort','asc')->get()->toArray();
        $packMenu = [];
        foreach ($menus as  $key => $item){
            $packMenu[$key]['label'] = $item['name'];
            $packMenu[$key]['value'] = $item['id'];
            $packMenu[$key]['parent_id'] = $item['parent_id'];
        }

        $menu = $this->buildTree($packMenu,0,'value');

        return $menu;
    }

    private function buildTree(array $elements, $parentId = 0,$pk='id')
    {
        $branch = [];
        foreach ($elements as $element) {
            if ($element['parent_id'] == $parentId) {
                $children = $this->buildTree($elements, $element[$pk],$pk);
                if ($children) {
                    $element['children'] = $children;
                }
                $branch[] = $element;
            }
        }

        return $branch;
    }


    public function list($params=[])
    {
        $model = Menu::whereNull('deleted_at');
        if(isset($params['name'])){
            $model->where('name','like','%'.$params['name'].'%');
        }
        $list = $model->orderBy('sort','asc')->orderBy('id','desc')->paginate();
        return $list;
    }

    public function store($params=[],$id=0)
    {

        $menu = null;
        if($id>0) {
            $menu = Menu::where('id', $id)->first();
            if (empty($menu)) {
                throw new Exception('未查询到数据');
            }
            $repeat = Menu::where('id', '<>', $id)->where(function($q) use ($params){
                $q->where('parent_id', $params['parentId']);
                $q->where('name',$params['name']);
            })->first();
        }else{
            $repeat = Menu::where(function($q) use ($params){
                $q->where('parent_id', $params['parentId']);
                $q->where('name',$params['name']);
            })->first();
        }

        if ($repeat) {
            throw new Exception('数据重复');
        }

        $add = [];
        $add["parent_id"]=$params['parentId'];
        $add["name"]= $params['name'];
        $add["sort"]= $params['sort'] ?? 0;
        $add["type"]= $params['type'];
        $add["route_name"]= $params['routeName'] ?? null;
        $add["route_path"]= $params['routePath'];
        $add["component"]= $params['component'];
        $add["perm"]= $params['perm'] ?? null;
        $add["visible"]= $params['visible'];
        $add["icon"]= $params['icon'];
        $add["redirect"]= $params['redirect'] ?? null;
        $add["keep_alive"]= $params['keepAlive'];
        $add["always_show"]= $params['alwaysShow'];
        $add["params"]= json_encode($params['params']);


        DB::beginTransaction();
        if(empty($menu)){
            $addResult = Menu::create($add);
            if($addResult === false){
                DB::rollBack();
            }
        }else{
            $updateResult = $menu->update($add);
            if($updateResult === false){
                DB::rollBack();
            }
        }
        DB::commit();

        return true;
    }

    public function show($id)
    {
        $result = Menu::where('id',$id)->first();
        if(empty($result)){
            return [];
        }
        return $result;
    }
    /**
     * delete
     */
    public function destroy($id)
    {
        $menu = Menu::find($id);
        if(empty($menu)){
            throw new Exception('数据不存在');
        }
        // 有子级不能删除
        $hasChildren = Menu::where('parent_id',$id)->count();
        if($hasChildren > 0){
            throw new Exception('存在子级，不能删除');
        }
        $result = Menu::where('id','=',$id)->delete();
        return $result;
    }



}
